#include "EditorCommonWindow.h"

#include "Widgets/Window.h"
#include "Widgets/RectangleWidget.h"
#include "Widgets/ImageWidget.h"
#include "Widgets/TextWidget.h"
#include "Widgets/Editor/DragWindowArea.h"
#include "Widgets/Editor/WindowResizeble.h"
#include "Widgets/Positioners/HorizontalPositionerWidget.h"
#include "Widgets/Mouse/MouseWidget.h"
#include "Widgets/WidgetAnimationTrigger.h"
#include "Widgets/WidgetAnimation.h"

#include "Asset/EngineDefaultPackage.h"
#include "Asset/EditorDefaultPackage.h"

WHE::SCommonWindowCreateResult WHE::CreateCommonWindow(const WHE::SCommonWindowCreateInfo& Info)
{
    TSharedObjectPtr<RWindow> Window = NewObject<RWindow>();
    RWindowWeakPtr WindowWeakPtr=Window;
    Window->HideSystemBorder();
    Window->SetWindowTitle(Info.Title);
    Window->SetWindowSize(Info.Size);



    auto Background=NewWidget<RRectangleWidget>(Window->GetRootWidget());
    Background->Anchor.Fill(Window->GetRootWidget());
    Background->FillColor=SColor::FromHexRGB(0x181818);
    
    const float TitleBarHeight=36;

    if(Info.bTitleBlinkEffectForModalWindow)
    {
        //add a tittle bar background
        auto TitleBarBackground=NewWidget<RRectangleWidget>(Window->GetRootWidget());
        TitleBarBackground->Height=TitleBarHeight;
        TitleBarBackground->Anchor.HorizontalFill(Window->GetRootWidget());

        auto BlinkTrigger=NewObject<RWidgetAnimationTrigger>(TitleBarBackground);
        BlinkTrigger->Duration=1.f;
        RWidgetAnimationTriggerWeakPtr BlinkTriggerWeakPtr=BlinkTrigger;

        Window->OnBlinkModalWindow.Bind([BlinkTriggerWeakPtr](){
            BlinkTriggerWeakPtr->Activate();
        });

        TitleBarBackground->FillColor=SAnimatedAttributeCreator::CreateColorBlinkAttribute(
            BlinkTrigger,
            SColor::FromHexRGB(0x181818),
            SColor::FromHexRGB(0x2B2B2B),
            0.2f
        );

    }

    auto MainVerticalLayout=NewWidget<RWidget>(Window->GetRootWidget());
    MainVerticalLayout->Anchor.Fill(Window->GetRootWidget());

    //enabble drag title bar
    {
        auto DragMoveWidget= NewWidget<RMouseDragWindowArea>(Window->GetRootWidget());
        DragMoveWidget->Height=TitleBarHeight;
        DragMoveWidget->Anchor.HorizontalFill(Window->GetRootWidget());
    }

    //customize resize
    if(Info.Resizeable)
    {
        auto Resizable= NewWidget<RWindowResizeble>(Window->GetRootWidget());
        Resizable->Anchor.Fill(Window->GetRootWidget());
    }

    //customize window buttons
    auto WindowButtons= NewWidget<RHorizontalPositionerWidget>(Window->GetRootWidget());
    {
        float WindowButtonWidth=34;
        WindowButtons->Anchor.RightReference=Window->GetRootWidget();
        WindowButtons->Width=WindowButtonWidth*
            (Info.MinimizeMaximizeButton?3:1);
        WindowButtons->Height=TitleBarHeight;
        WindowButtons->Spacing=0;

        //Minimize
        float WindowButtonImageSize=15;

        if(Info.MinimizeMaximizeButton)
        {
            auto Minimize= NewWidget<RRectangleWidget>(WindowButtons);
            Minimize->FillColor=SColor::FromHexRGB(0x373737);

            Minimize->Width=WindowButtonWidth;
            Minimize->Anchor.VerticalFill(WindowButtons);

            auto MinimizeImage= NewWidget<RImageWidget>(Minimize);
            auto Image=REditorDefaultPackage::Get()->GetMinimizeIcon(); 
            MinimizeImage->Image=Image;
            MinimizeImage->Width=WindowButtonImageSize;
            MinimizeImage->Height=WindowButtonImageSize;
            MinimizeImage->Anchor.CenterIn(Minimize);

            auto Mouse=NewWidget<RMouseWidget>(Minimize);
            Mouse->Anchor.Fill(Minimize);

            TWeakObjectPtr<RMouseWidget> MouseWeakPtr=Mouse;
            Minimize->Fill=[MouseWeakPtr]()->bool{
                return MouseWeakPtr->IsHovered();
            };

            Mouse->OnClicked.BindLambda([Minimize,WindowWeakPtr](const SMouseButtonEvent&)->bool{
                WindowWeakPtr->Minimize();
                return true;
            });
        }

        //restore
        if(Info.MinimizeMaximizeButton)
        {
            auto Restore= NewWidget<RRectangleWidget>(WindowButtons);
            Restore->Width=WindowButtonWidth;
            Restore->Anchor.VerticalFill(WindowButtons);
            Restore->FillColor=SColor::FromHexRGB(0x373737);

            auto RestoreImageWidget= NewWidget<RImageWidget>(Restore); 
            RestoreImageWidget->Image=[WindowWeakPtr]()->RTexture2DPtr{
                return 
                    WindowWeakPtr->IsMaximized()?
                    REditorDefaultPackage::Get()->GetRestoreIcon():
                    REditorDefaultPackage::Get()->GetMaximizeIcon();
            };
            RestoreImageWidget->Width=WindowButtonImageSize;
            RestoreImageWidget->Height=WindowButtonImageSize;
            RestoreImageWidget->Anchor.CenterIn(Restore);



            auto Mouse=NewWidget<RMouseWidget>(Restore);
            Mouse->Anchor.Fill(Restore);

            TWeakObjectPtr<RMouseWidget> MouseWeakPtr=Mouse;
            Restore->Fill=[MouseWeakPtr]()->bool{
                return MouseWeakPtr->IsHovered();
            };

            Mouse->OnClicked.BindLambda([WindowWeakPtr](const SMouseButtonEvent&)->bool{
                if(WindowWeakPtr->IsMaximized())
                {
                    WindowWeakPtr->Restore();
                }else
                {
                    WindowWeakPtr->Maximize();
                }
                return true;
            });
        }

        //close
        {
            auto Close= NewWidget<RRectangleWidget>(WindowButtons);
            Close->Width=WindowButtonWidth;
            Close->Anchor.VerticalFill(WindowButtons);
            Close->FillColor=SColor::FromHexRGB(0xE81123);

            auto CloseImage= NewWidget<RImageWidget>(Close);
            CloseImage->Image=REditorDefaultPackage::Get()->GetCloseIcon();
            CloseImage->Width=WindowButtonImageSize;
            CloseImage->Height=WindowButtonImageSize;
            CloseImage->Anchor.CenterIn(Close);

            auto Mouse=NewWidget<RMouseWidget>(Close);
            Mouse->Anchor.Fill(Close);

            Close->Fill=[Mouse]()->bool{
                return Mouse->IsHovered();
            };

            Mouse->OnClicked.BindLambda([WindowWeakPtr](const SMouseButtonEvent&)->bool{
                WindowWeakPtr->Close();
                return true;
            });
        }

    }


    TSharedObjectPtr<RWidget> TitleMenuBar=NewWidget<RWidget>(MainVerticalLayout);
    TitleMenuBar->Height=TitleBarHeight;

    //add icon
    auto Icon= NewWidget<RImageWidget>(TitleMenuBar);
    {
        Icon->Image=REngineDefaultPackage::Get()->GetEngineIcon();
        Icon->Width=32.f;
        Icon->Height=32.f;
        Icon->Anchor.LeftReference=TitleMenuBar;
        Icon->Anchor.LeftReferenceEdge=EHorizontalWidgetEdge::Left;
        Icon->Anchor.LeftOffset=3;
        Icon->Anchor.VerticalFill(TitleMenuBar);
    }

    //add title if have
    if(!Info.Title.IsEmpty())
    {
        auto Title= NewWidget<RTextWidget>(TitleMenuBar);
        Title->Text=Info.Title;
        Title->FontSize=14;
        Title->VerticalAlignment=ETextVerticalAlignment::Center;
        Title->Anchor.LeftReference=Icon;
        Title->Anchor.LeftReferenceEdge=EHorizontalWidgetEdge::Right;
        Title->Anchor.LeftOffset=5;
        Title->Anchor.VerticalFill(TitleMenuBar);
    }

    //add a grey spliter
    auto Spliter= NewWidget<RRectangleWidget>(MainVerticalLayout);
    {
        Spliter->Height=1;
        Spliter->FillColor=SColor::FromHexRGB(0x2B2B2B);
        Spliter->Anchor.TopReference=TitleMenuBar;
        Spliter->Anchor.TopOffset=TitleBarHeight;
        Spliter->Anchor.HorizontalFill(MainVerticalLayout);
    }

    //add content
    auto WindowContent=NewWidget<RWidget>(MainVerticalLayout);
    WindowContent->Anchor.HorizontalFill(MainVerticalLayout);
    WindowContent->Anchor.TopReference=Spliter;
    WindowContent->Anchor.TopReferenceEdge=EVerticalWidgetEdge::Bottom;
    WindowContent->Anchor.BottomReference=MainVerticalLayout;

    SCommonWindowCreateResult Result;
    Result.Window=Window;
    Result.WindowContent=WindowContent;
    return Result;
}